<!doctype html>
<html>
  <head>
    <title>
      Test Warning Messages for Value Setter are Produced
    </title>
    <script src="../../resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit-util.js"></script>
    <script src="../resources/audit.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      let audit = Audit.createTaskRunner({requireResultFile: true});

      audit.define({label: 'test-0'}, (task, should) => {
        runTest(
            task.label, should,
            [
              {methodName: 'setValueAtTime', args: [0, 0]},
              {methodName: 'setValueAtTime', args: [1, 0.2]},
              {methodName: 'linearRampToValueAtTime', args: [99, 0.7]},
            ],
            [
              // No overlap, so no warning
              {time: 0.1, value: -1},
              // Overlaps setValue to linearRamp
              {time: 0.5, value: 99},
              // Past end of linearRamp, so no warning
              {time: 0.9, value: 50}
            ])
            .then(() => task.done());
      });

      audit.define({label: 'test-1'}, (task, should) => {
        runTest(
            task.label, should,
            [
              {methodName: 'setValueAtTime', args: [0, 0]},
              {methodName: 'linearRampToValueAtTime', args: [1, 0.21]},
              {methodName: 'linearRampToValueAtTime', args: [99, 0.71]},
            ],
            [
              // Overlaps setValue to linearRamp
              {time: 0.1, value: -1},
              // Overlaps linearRamp to linearRamp
              {time: 0.5, value: 99},
              // Past end of linearRamp, so no warning
              {time: 0.9, value: 50}
            ])
            .then(() => task.done());
      });

      audit.define({label: 'test-2'}, (task, should) => {
        runTest(
            task.label, should,
            [
              {methodName: 'setValueAtTime', args: [0, 0]},
              {methodName: 'linearRampToValueAtTime', args: [1, 0.22]},
              {methodName: 'setValueAtTime', args: [99, 0.72]},
            ],
            [
              // Overlaps setValue to linearRamp
              {time: 0.1, value: -1},
              // Between end of linearRamp and start of setValue, so no warning.
              {time: 0.5, value: 99},
            ])
            .then(() => task.done());
      });

      audit.define({label: 'test-3'}, (task, should) => {
        runTest(
            task.label, should,
            [
              {methodName: 'setValueAtTime', args: [0, 0]},
              {methodName: 'linearRampToValueAtTime', args: [1, 0.23]},
              {methodName: 'setValueAtTime', args: [99, 0.73]},
            ],
            [
              // Overlaps setValue to linearRamp
              {time: 0.1, value: -1},
              // Between end of linearRamp and start of setValue, so no warning.
              {time: 0.5, value: 99},
            ])
            .then(() => task.done());
      });

      audit.define({label: 'test-4'}, (task, should) => {
        runTest(
            task.label, should,
            [
              {methodName: 'setValueAtTime', args: [0, 0]},
              {methodName: 'setTargetAtTime', args: [1, 0.24, .1]},
            ],
            [
              // No overlap.
              {time: 0.1, value: -1},
              // Overlaps setTarget
              {time: 0.5, value: 99},
            ])
            .then(() => task.done());
      });

      audit.define({label: 'test-5'}, (task, should) => {
        runTest(
            task.label, should,
            [
              {methodName: 'setValueAtTime', args: [0, 0]},
              {methodName: 'setValueCurveAtTime', args: [[1, 2, 3], 0.25, .5]},
            ],
            [
              // No overlap.
              {time: 0.1, value: -1},
              // Overlaps setValueCurve
              {time: 0.5, value: 99, shouldThrow: true},
              // Past end of setValueCurve, so no warning
              {time: .9, value: 50}
            ])
            .then(() => task.done());
      });

      audit.run();

      // Run test with automations given in |automationList| and with value
      // setters given in |valueSetterList|.
      function runTest(taskLabel, should, automationList, valueSetterList) {
        // This log message is to make it easier to see where the warnings
        // messages come from in the logs.
        console.log('Test: ' + taskLabel);

        // Fairly arbitrary duration and sample rate.
        let context = new OfflineAudioContext(1, 48000, 48000);

        // For simplicity, just do the automations on a ConstantSourceNode.
        let src = new ConstantSourceNode(context);
        src.connect(context.destination);

        // Set up automations.
        for (let item of automationList) {
          src.offset[item.methodName](...item.args);
        }

        // Suspend the context at the specified times and directly set the
        // value.
        for (let item of valueSetterList) {
          context.suspend(item.time)
              .then(() => {
                if (item.shouldThrow === true) {
                  should(() => src.offset.value = item.value,
                    'Value setter overlaps setValueCurve')
                    .throw(DOMException, 'NotSupportedError');
                } else {
                  src.offset.value = item.value;
                }
              })
              .then(() => context.resume());
        }

        src.start();

        return context.startRendering().then(() => {
          should(true, taskLabel).message(': rendered successfully', 'FAILED');
        });
      }
    </script>
  </body>
</html>
